#pragma once
#include <map>
#include <string>
#include <vector>
#include "ImportExport.h"

namespace ja2{ namespace utils
{
	//! Section.
	class Section
	{
		// Typedefs
	public:
		typedef std::vector<std::string> StringVector_t;
	private:
		//! Vector of property values.
		typedef std::vector<std::string> PropertiesVector_t;
		//! Property map.
		typedef std::map<std::string, PropertiesVector_t> PropertiesMap_t;

		// Attributes
	private:
		//! Property map.
		PropertiesMap_t m_Properties;

		// Operations
	public:
		//! Key exist.
		JA2_UTILS_API bool exist(std::string const &Key) const;
		//! Add key, value.
		JA2_UTILS_API void add(std::string const &Key, std::string const &Value);
		//! Create new key only.
		JA2_UTILS_API void add(std::string const &Key);
		//! Set new value for key. 
		JA2_UTILS_API void set(std::string const &Key, std::string const &Value);
		//! Get value for key with default value if Key is not found.
		/*!
			/return true if value is found for given key. Otherwise false. Value receive last value inserted in container.
		*/
		JA2_UTILS_API std::string get_string_value(std::string const &Key, std::string const &Default = std::string()) const;
		//! Get bool value.
		JA2_UTILS_API bool get_bool_value(std::string const &Key) const;
		//! Get bool value. Use default if not found.
		JA2_UTILS_API bool get_bool_value_default(std::string const &Key, bool Default) const;
		//! Get string vector.
		JA2_UTILS_API StringVector_t get_string_vector(std::string const &Key) const;
		//! Get string vector./return true if Key was found.
		JA2_UTILS_API bool get_string_vector(std::string const &Key, StringVector_t &Values) const;
		//! Get long value.
		JA2_UTILS_API std::int_least32_t get_long_value(std::string const &Key) const;
		//! Specialization for int.
		JA2_UTILS_API std::int_least32_t get_long_value_default(std::string const &Key, long Default) const;
		//! Print the values to output stream.
		JA2_UTILS_API void print(std::ostream& out, std::string const &Prefix = std::string()) const;
		//! Clear the section.
		JA2_UTILS_API void clear();
	private:
		//! Get value for key.
		/*!
			/return true if value is found for given key. Otherwise false. Values receive all values.
		*/
		bool get_value(std::string const &Key, PropertiesVector_t &Values) const;
		//! Get value for key.
		/*!
			/return true if value is found for given key. Otherwise false. Value receive last value.
		*/
		bool get_value(std::string const &Key, std::string &Value) const;
		//! Get value for key with default value if Key is not found.
		/*!
			/return true if value is found for given key. Otherwise false. Value receive last value.
		*/
		bool get_value_default(std::string const &Key, std::string &Value, std::string const &Default = std::string()) const;
		//! Get values for key. If value doesn't exist, create one.
		PropertiesVector_t &get_value(std::string const &Key);
		//! Get const values for key. If value doesn't exist, create one.
		PropertiesVector_t const &get_value(std::string const &Key) const;
	};

	//! Container of properties.
	class PropertyContainer
	{
		// Typedefs
	public:
		typedef std::map<std::string, Section> SectionMap_t;

		// Attributes
	private:
		//! Sections.
		SectionMap_t m_Sections;

		// Operations
	public:
		//! Clear all sections.
		JA2_UTILS_API void clear();
		//! Find if section exists.
		JA2_UTILS_API bool section_exists(std::string const &Section) const;
		//! Get section. If section doesn't exist, create one.
		JA2_UTILS_API Section &get_section(std::string const &Section);
		//! Get section. If section doesn't exist throw.
		JA2_UTILS_API Section const &get_section(std::string const &Section) const;
		//! Print all properties.
		JA2_UTILS_API void print(std::ostream &Out) const;

		// Construction/Destruction
	public:
		// Default.
		PropertyContainer() {};
		PropertyContainer(PropertyContainer &&Rvalue);
	};
} /*utils*/} /*ja2*/
